require 'luacov'
local Delaunay       = (require "delaunay")
local Point          = Delaunay.Point
local Triangle       = Delaunay.Triangle

context("Delaunay", function()

  test('is a module containing binding to Point, Edge, Triangle primitives', function()
    assert_true(type(Delaunay) == 'table')
    assert_true(type(Delaunay.Point) == 'table')
    assert_true(type(Delaunay.Edge) == 'table')
    assert_true(type(Delaunay.Triangle) == 'table')
  end)
  
  it('offers a triangulation function', function()
    assert_true(type(Delaunay.triangulate) == 'function')
  end)
  
  it('also have a _VERSION member', function()
    assert_true(type(Delaunay._VERSION) == 'string')
  end)  

  should('throw an error when receiving a vertex', function()
    local function triangulate1vertex()
      Delaunay.triangulate(Point())
    end
    assert_error(triangulate1vertex)
  end)    

  should('throw an error when receiving two vertices', function()
    local function triangulate2vertices()
      Delaunay.triangulate(Point(), Point(1,1))
    end
    assert_error(triangulate2vertices)
  end)
  
  should('return a unique triangle made when receiving 3 vertices', function()
    local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
    local t = Delaunay.triangulate(p1, p2, p3)
    assert_equal(#t, 1)
    assert_equal(getmetatable(t[1]), Triangle)
    assert_equal(t[1].p1, p1)
    assert_equal(t[1].p2, p2)
    assert_equal(t[1].p3, p3)
  end)
  
  should('return 2 triangles for those 4 vertices', function()
    local p1, p2, p3, p4 = Point(), Point(1,0), Point(1,1), Point(0,1)
    local t = Delaunay.triangulate(p1, p2, p3, p4)
    assert_equal(#t, 2)
    assert_equal(getmetatable(t[1]), Triangle)    
    assert_equal(t[1].p1, p2)
    assert_equal(t[1].p2, p1)
    assert_equal(t[1].p3, p4)
    assert_equal(getmetatable(t[2]), Triangle)    
    assert_equal(t[2].p1, p3)
    assert_equal(t[2].p2, p2)
    assert_equal(t[2].p3, p4)  
  end)
  
  should('return 4 triangles for those 5 vertices', function()
    local p1, p2, p3, p4, p5 = Point(), Point(1,0), Point(1,1), Point(0,1), Point(0.5, 0.5)
    local t = Delaunay.triangulate(p1, p2, p3, p4, p5)
    assert_equal(#t, 4)
    assert_equal(getmetatable(t[1]), Triangle)    
    assert_equal(t[1].p1, p3)
    assert_equal(t[1].p2, p2)
    assert_equal(t[1].p3, p5)
    assert_equal(getmetatable(t[2]), Triangle)    
    assert_equal(t[2].p1, p4)
    assert_equal(t[2].p2, p3)
    assert_equal(t[2].p3, p5)
    assert_equal(getmetatable(t[3]), Triangle)    
    assert_equal(t[3].p1, p2)
    assert_equal(t[3].p2, p1)
    assert_equal(t[3].p3, p5)
    assert_equal(getmetatable(t[4]), Triangle)    
    assert_equal(t[4].p1, p1)
    assert_equal(t[4].p2, p4)
    assert_equal(t[4].p3, p5)      
  end)

	should('return 3 triangles for those 4 vertices', function()
    local p1, p2, p3, p4 = Point(0,0), Point(200,1), Point(400,0), Point(300,5)
    local t = Delaunay.triangulate(p1, p2, p3, p4)
    assert_equal(#t, 3)
    assert_equal(getmetatable(t[1]), Triangle)    
    assert_equal(t[1].p1, p1)
    assert_equal(t[1].p2, p2)
    assert_equal(t[1].p3, p3)
    assert_equal(getmetatable(t[2]), Triangle)    
    assert_equal(t[2].p1, p3)
    assert_equal(t[2].p2, p2)
    assert_equal(t[2].p3, p4)
    assert_equal(getmetatable(t[3]), Triangle)    
    assert_equal(t[3].p1, p2)
    assert_equal(t[3].p2, p1)
    assert_equal(t[3].p3, p4)     
  end)
  
end)